from flask import Blueprint, request, session, render_template, redirect, url_for, flash

from auth import login_required
from logger_config import get_logger
from services.cost_service import cost_service
from services.query_service import query_service
from services.user_service import user_service
from services.conversation_file_service import ConversationFileService
from utils.response_utils import create_api_response

logger = get_logger(__name__)

# 创建用户蓝图
user_bp = Blueprint('user', __name__, url_prefix='/user')


@user_bp.route('/register', methods=['GET', 'POST'])
def register():
    """用户注册"""
    if request.method == 'GET':
        return render_template('auth/register.html')

    try:
        data = request.get_json() if request.is_json else request.form

        # 验证必需字段
        required_fields = ['username', 'email', 'password']
        for field in required_fields:
            if not data or field not in data or not data[field]:
                if request.is_json:
                    return create_api_response(
                    None,
                    success=False,
                    message=f"缺少必需字段: {field}",
                    status_code=400
                )
                else:
                    flash(f"缺少必需字段: {field}", 'error')
                    return render_template('auth/register.html')

        username = data['username'].strip()
        email = data['email'].strip()
        password = data['password']

        # 创建用户
        result = user_service.create_user(username, email, password)

        if result['success']:
            logger.info(f"用户注册成功: {username}")

            if request.is_json:
                return create_api_response({
                    'user_id': result['user_id']
                }, message=result['message'])
            else:
                flash('注册成功，请登录', 'success')
                return redirect(url_for('user.login'))
        else:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message=result['error'],
                    status_code=400
                )
            else:
                flash(result['error'], 'error')
                return render_template('auth/register.html')

    except Exception as e:
        logger.error(f"用户注册失败: {str(e)}")
        if request.is_json:
            response = create_api_response(
                None,
                success=False,
                message=f"注册失败: {str(e)}"
            )

            response.status_code = 500

            return response
        else:
            flash(f"注册失败: {str(e)}", 'error')
            return render_template('auth/register.html')


@user_bp.route('/login', methods=['GET', 'POST'])
def login():
    """用户登录"""
    if request.method == 'GET':
        return render_template('auth/login.html')

    try:
        data = request.get_json() if request.is_json else request.form

        if not data or 'username' not in data or 'password' not in data:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="请提供用户名和密码",
                    status_code=400
                )
            else:
                flash("请提供用户名和密码", 'error')
                return render_template('auth/login.html')

        username = data['username'].strip()
        password = data['password']

        # 用户认证
        result = user_service.authenticate_user(username, password)

        if result['success']:
            # 设置会话
            user_info = result['user']
            session['user_id'] = user_info['id']
            session['username'] = user_info['username']
            session['role'] = user_info['role']
            session['logged_in'] = True

            logger.info(f"用户登录成功: {username}")

            if request.is_json:
                return create_api_response({
                    'user': user_info,
                    'token': result['token']
                }, message="登录成功")
            else:
                flash('登录成功', 'success')
                # 根据用户角色重定向
                if user_info['role'] == 'admin':
                    return redirect(url_for('admin.dashboard'))
                else:
                    return redirect(url_for('main.dashboard'))
        else:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message=result['error'],
                    status_code=401
                )
            else:
                flash(result['error'], 'error')
                return render_template('auth/login.html')

    except Exception as e:
        logger.error(f"用户登录失败: {str(e)}")
        if request.is_json:
            response = create_api_response(
                None,
                success=False,
                message=f"登录失败: {str(e)}"
            )

            response.status_code = 500

            return response
        else:
            flash(f"登录失败: {str(e)}", 'error')
            return render_template('auth/login.html')


@user_bp.route('/logout', methods=['GET', 'POST'])
@login_required
def logout():
    """用户登出"""
    try:
        username = session.get('username')

        # 清除会话
        session.clear()

        logger.info(f"用户登出: {username}")

        if request.is_json:
            return create_api_response(None, message="登出成功")
        else:
            flash('已成功登出', 'info')
            return redirect(url_for('user.login'))

    except Exception as e:
        logger.error(f"用户登出失败: {str(e)}")
        if request.is_json:
            response = create_api_response(
                None,
                success=False,
                message=f"登出失败: {str(e)}"
            )

            response.status_code = 500

            return response
        else:
            flash(f"登出失败: {str(e)}", 'error')
            return redirect(url_for('main.index'))


@user_bp.route('/profile')
@login_required
def profile():
    """用户资料页面"""
    try:
        user_id = session.get('user_id')
        user_info = user_service.get_user_by_id(user_id)

        if not user_info:
            flash('用户信息不存在', 'error')
            return redirect(url_for('main.dashboard'))

        # 获取用户查询统计
        query_stats = query_service.get_user_query_stats(user_id)

        # 获取用户成本摘要
        cost_summary = cost_service.get_user_cost_summary(user_id, days=30)

        # 获取最近的查询历史
        recent_queries = query_service.get_query_history(user_id, limit=10)

        return render_template('user/profile.html',
                               user=user_info,
                               query_stats=query_stats,
                               cost_summary=cost_summary,
                               recent_queries=recent_queries)

    except Exception as e:
        logger.error(f"加载用户资料失败: {str(e)}")
        flash(f"加载用户资料失败: {str(e)}", 'error')
        return redirect(url_for('main.dashboard'))


@user_bp.route('/profile/edit', methods=['GET', 'POST'])
@login_required
def edit_profile():
    """编辑用户资料"""
    user_id = session.get('user_id')

    if request.method == 'GET':
        user_info = user_service.get_user_by_id(user_id)
        if not user_info:
            flash('用户信息不存在', 'error')
            return redirect(url_for('user.profile'))
        return render_template('user/edit_profile.html', user=user_info)

    try:
        data = request.get_json() if request.is_json else request.form

        if not data:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="请提供要更新的数据",
                    status_code=400
                )
            else:
                flash("请提供要更新的数据", 'error')
                return redirect(url_for('user.edit_profile'))

        # 更新用户资料
        update_data = {}
        if 'email' in data and data['email']:
            update_data['email'] = data['email'].strip()

        if update_data:
            result = user_service.update_user_profile(user_id, **update_data)

            if result['success']:
                if request.is_json:
                    return create_api_response(None, message=result['message'])
                else:
                    flash(result['message'], 'success')
                    return redirect(url_for('user.profile'))
            else:
                if request.is_json:
                    return create_api_response(
                        None,
                        success=False,
                        message=result['error'],
                        status_code=400
                    )
                else:
                    flash(result['error'], 'error')
                    return redirect(url_for('user.edit_profile'))
        else:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="没有提供有效的更新数据",
                    status_code=400
                )
            else:
                flash("没有提供有效的更新数据", 'warning')
                return redirect(url_for('user.edit_profile'))

    except Exception as e:
        logger.error(f"更新用户资料失败: {str(e)}")
        if request.is_json:
            response = create_api_response(
                None,
                success=False,
                message=f"更新失败: {str(e)}"
            )

            response.status_code = 500

            return response
        else:
            flash(f"更新失败: {str(e)}", 'error')
            return redirect(url_for('user.edit_profile'))


@user_bp.route('/change-password', methods=['GET', 'POST'])
@login_required
def change_password():
    """修改密码"""
    if request.method == 'GET':
        return render_template('user/change_password.html')

    try:
        data = request.get_json() if request.is_json else request.form

        if not data or 'old_password' not in data or 'new_password' not in data:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="请提供旧密码和新密码",
                    status_code=400
                )
            else:
                flash("请提供旧密码和新密码", 'error')
                return render_template('user/change_password.html')

        user_id = session.get('user_id')
        old_password = data['old_password']
        new_password = data['new_password']

        # 修改密码
        result = user_service.change_password(user_id, old_password, new_password)

        if result['success']:
            if request.is_json:
                return create_api_response(None, message=result['message'])
            else:
                flash(result['message'], 'success')
                return redirect(url_for('user.profile'))
        else:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message=result['error'],
                    status_code=400
                )
            else:
                flash(result['error'], 'error')
                return render_template('user/change_password.html')

    except Exception as e:
        logger.error(f"修改密码失败: {str(e)}")
        if request.is_json:
            response = create_api_response(
                None,
                success=False,
                message=f"修改密码失败: {str(e)}"
            )

            response.status_code = 500

            return response
        else:
            flash(f"修改密码失败: {str(e)}", 'error')
            return render_template('user/change_password.html')


@user_bp.route('/queries')
@login_required
def query_history():
    """查询历史页面"""
    try:
        user_id = session.get('user_id')
        page = request.args.get('page', 1, type=int)
        per_page = request.args.get('per_page', 20, type=int)

        # 限制每页数量
        per_page = min(per_page, 100)

        offset = (page - 1) * per_page
        queries = query_service.get_query_history(user_id, per_page, offset)

        # 获取用户查询统计
        query_stats = query_service.get_user_query_stats(user_id)

        return render_template('user/query_history.html',
                               queries=queries,
                               query_stats=query_stats,
                               page=page,
                               per_page=per_page)

    except Exception as e:
        logger.error(f"加载查询历史失败: {str(e)}")
        flash(f"加载查询历史失败: {str(e)}", 'error')
        return redirect(url_for('main.dashboard'))


@user_bp.route('/queries/<int:query_id>')
@login_required
def query_detail(query_id):
    """查询详情页面"""
    try:
        user_id = session.get('user_id')
        query = query_service.get_query_by_id(query_id, user_id)

        if not query:
            flash('查询记录不存在或无权访问', 'error')
            return redirect(url_for('user.query_history'))

        return render_template('user/query_detail.html', query=query)

    except Exception as e:
        logger.error(f"加载查询详情失败: {str(e)}")
        flash(f"加载查询详情失败: {str(e)}", 'error')
        return redirect(url_for('user.query_history'))


@user_bp.route('/queries/<int:query_id>/delete', methods=['POST'])
@login_required
def delete_query(query_id):
    """删除查询记录"""
    try:
        user_id = session.get('user_id')
        success = query_service.delete_query(query_id, user_id)

        if success:
            if request.is_json:
                return create_api_response(None, message="查询记录删除成功")
            else:
                flash('查询记录删除成功', 'success')
        else:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="查询记录不存在或删除失败",
                    status_code=404
                )
            else:
                flash('查询记录不存在或删除失败', 'error')

        if not request.is_json:
            return redirect(url_for('user.query_history'))

    except Exception as e:
        logger.error(f"删除查询记录失败: {str(e)}")
        if request.is_json:
            response = create_api_response(
                None,
                success=False,
                message=f"删除查询记录失败: {str(e)}"
            )

            response.status_code = 500

            return response
        else:
            flash(f"删除查询记录失败: {str(e)}", 'error')
            return redirect(url_for('user.query_history'))


@user_bp.route('/cost-summary')
@login_required
def cost_summary():
    """用户成本摘要页面"""
    try:
        user_id = session.get('user_id')
        days = request.args.get('days', 30, type=int)
        days = min(days, 365)  # 限制最大天数

        # 获取用户成本摘要
        cost_summary_data = cost_service.get_user_cost_summary(user_id, days)

        # 获取用户查询统计
        query_stats = query_service.get_user_query_stats(user_id)

        return render_template('user/cost_summary.html',
                               cost_summary=cost_summary_data,
                               query_stats=query_stats,
                               days=days)

    except Exception as e:
        logger.error(f"加载成本摘要失败: {str(e)}")
        flash(f"加载成本摘要失败: {str(e)}", 'error')
        return redirect(url_for('main.dashboard'))


@user_bp.route('/settings')
@login_required
def settings():
    """用户设置页面"""
    try:
        user_id = session.get('user_id')
        user_info = user_service.get_user_by_id(user_id)

        if not user_info:
            flash('用户信息不存在', 'error')
            return redirect(url_for('main.dashboard'))

        return render_template('user/settings.html', user=user_info)

    except Exception as e:
        logger.error(f"加载用户设置失败: {str(e)}")
        flash(f"加载用户设置失败: {str(e)}", 'error')
        return redirect(url_for('main.dashboard'))


# API端点用于AJAX请求
@user_bp.route('/api/validate-username', methods=['POST'])
def validate_username():
    """验证用户名是否可用"""
    try:
        data = request.get_json()

        if not data or 'username' not in data:
            return create_api_response(
                None,
                success=False,
                message="请提供用户名",
                status_code=400
            )

        username = data['username'].strip()

        if not username:
            return create_api_response(
                None,
                success=False,
                message="用户名不能为空",
                status_code=400
            )

        # 检查用户名是否已存在
        existing_user = user_service.get_user_by_username(username)

        if existing_user:
            return create_api_response({
                'available': False,
                'message': '用户名已存在'
            })
        else:
            return create_api_response({
                'available': True,
                'message': '用户名可用'
            })

    except Exception as e:
        logger.error(f"验证用户名失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"验证用户名失败: {str(e)}"
        )

        response.status_code = 500

        return response


# 对话文件管理路由
@user_bp.route('/conversations')
@login_required
def user_conversations():
    """获取用户的对话文件列表"""
    try:
        user_id = session.get('user_id')
        page = request.args.get('page', 1, type=int)
        per_page = request.args.get('per_page', 20, type=int)
        
        conversation_service = ConversationFileService()
        conversations = conversation_service.get_user_conversations(
            user_id=user_id,
            page=page,
            per_page=per_page
        )
        
        if request.is_json:
            return create_api_response(conversations)
        else:
            return render_template('user/conversations.html', conversations=conversations)
            
    except Exception as e:
        logger.error(f"获取用户对话文件失败: {str(e)}")
        if request.is_json:
            return create_api_response(
                None,
                success=False,
                message=f"获取对话文件失败: {str(e)}",
                status_code=500
            )
        else:
            flash(f"获取对话文件失败: {str(e)}", 'error')
            return redirect(url_for('user.profile'))


@user_bp.route('/conversations/<int:conversation_id>')
@login_required
def conversation_detail(conversation_id):
    """获取对话文件详情"""
    try:
        user_id = session.get('user_id')
        conversation_service = ConversationFileService()
        
        # 获取对话记录
        conversation = conversation_service.get_conversation_by_id(conversation_id)
        
        if not conversation or conversation.user_id != user_id:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="对话文件不存在或无权访问",
                    status_code=404
                )
            else:
                flash("对话文件不存在或无权访问", 'error')
                return redirect(url_for('user.user_conversations'))
        
        # 获取对话内容
        content = conversation_service.get_conversation_content(conversation_id)
        
        if request.is_json:
            return create_api_response({
                'conversation': {
                    'id': conversation.id,
                    'user_id': conversation.user_id,
                    'conversation_dir': conversation.conversation_dir,
                    'timestamp_folder': conversation.timestamp_folder,
                    'files': conversation.files,
                    'created_at': conversation.created_at.isoformat(),
                    'updated_at': conversation.updated_at.isoformat() if conversation.updated_at else None
                },
                'content': content
            })
        else:
            return render_template('user/conversation_detail.html', 
                                 conversation=conversation, content=content)
            
    except Exception as e:
        logger.error(f"获取对话文件详情失败: {str(e)}")
        if request.is_json:
            return create_api_response(
                None,
                success=False,
                message=f"获取对话文件详情失败: {str(e)}",
                status_code=500
            )
        else:
            flash(f"获取对话文件详情失败: {str(e)}", 'error')
            return redirect(url_for('user.user_conversations'))


@user_bp.route('/conversations/<int:conversation_id>/delete', methods=['POST'])
@login_required
def delete_user_conversation(conversation_id):
    """删除用户的对话文件"""
    try:
        user_id = session.get('user_id')
        conversation_service = ConversationFileService()
        
        # 获取对话记录
        conversation = conversation_service.get_conversation_by_id(conversation_id)
        
        if not conversation or conversation.user_id != user_id:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="对话文件不存在或无权访问",
                    status_code=404
                )
            else:
                flash("对话文件不存在或无权访问", 'error')
                return redirect(url_for('user.user_conversations'))
        
        # 删除对话文件
        success = conversation_service.delete_conversation(conversation_id)
        
        if success:
            logger.info(f"用户 {user_id} 删除对话文件 {conversation_id} 成功")
            if request.is_json:
                return create_api_response(
                    {'message': '对话文件删除成功'},
                    message="对话文件删除成功"
                )
            else:
                flash("对话文件删除成功", 'success')
                return redirect(url_for('user.user_conversations'))
        else:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="删除对话文件失败",
                    status_code=500
                )
            else:
                flash("删除对话文件失败", 'error')
                return redirect(url_for('user.user_conversations'))
            
    except Exception as e:
        logger.error(f"删除对话文件失败: {str(e)}")
        if request.is_json:
            return create_api_response(
                None,
                success=False,
                message=f"删除对话文件失败: {str(e)}",
                status_code=500
            )
        else:
            flash(f"删除对话文件失败: {str(e)}", 'error')
            return redirect(url_for('user.user_conversations'))


@user_bp.route('/conversations/<int:conversation_id>/download')
@login_required
def download_conversation(conversation_id):
    """下载对话文件归档"""
    try:
        user_id = session.get('user_id')
        conversation_service = ConversationFileService()
        
        # 获取对话记录
        conversation = conversation_service.get_conversation_by_id(conversation_id)
        
        if not conversation or conversation.user_id != user_id:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="对话文件不存在或无权访问",
                    status_code=404
                )
            else:
                flash("对话文件不存在或无权访问", 'error')
                return redirect(url_for('user.user_conversations'))
        
        # 创建下载归档
        archive_path = conversation_service.create_download_archive(conversation_id)
        
        if archive_path:
            from flask import send_file
            import os
            
            filename = f"conversation_{conversation_id}_{conversation.timestamp_folder}.zip"
            
            return send_file(
                archive_path,
                as_attachment=True,
                download_name=filename,
                mimetype='application/zip'
            )
        else:
            if request.is_json:
                return create_api_response(
                    None,
                    success=False,
                    message="创建下载归档失败",
                    status_code=500
                )
            else:
                flash("创建下载归档失败", 'error')
                return redirect(url_for('user.user_conversations'))
            
    except Exception as e:
        logger.error(f"下载对话文件失败: {str(e)}")
        if request.is_json:
            return create_api_response(
                None,
                success=False,
                message=f"下载对话文件失败: {str(e)}",
                status_code=500
            )
        else:
            flash(f"下载对话文件失败: {str(e)}", 'error')
            return redirect(url_for('user.user_conversations'))


@user_bp.route('/conversations/stats')
@login_required
def user_conversation_stats():
    """获取用户对话文件统计"""
    try:
        user_id = session.get('user_id')
        conversation_service = ConversationFileService()
        
        # 获取用户存储统计
        stats = conversation_service.get_storage_stats(user_id=user_id)
        
        if request.is_json:
            return create_api_response(stats)
        else:
            return render_template('user/conversation_stats.html', stats=stats)
            
    except Exception as e:
        logger.error(f"获取用户对话文件统计失败: {str(e)}")
        if request.is_json:
            return create_api_response(
                None,
                success=False,
                message=f"获取对话文件统计失败: {str(e)}",
                status_code=500
            )
        else:
            flash(f"获取对话文件统计失败: {str(e)}", 'error')
            return redirect(url_for('user.profile'))


@user_bp.route('/api/check-session', methods=['GET'])
def check_session():
    """检查用户会话状态"""
    try:
        if 'logged_in' in session and session['logged_in']:
            return create_api_response({
                'logged_in': True,
                'user_id': session.get('user_id'),
                'username': session.get('username'),
                'role': session.get('role')
            })
        else:
            return create_api_response({
                'logged_in': False
            })

    except Exception as e:
        logger.error(f"检查会话状态失败: {str(e)}")
        response = create_api_response(
            None,
            success=False,
            message=f"检查会话状态失败: {str(e)}"
        )

        response.status_code = 500

        return response
